package stat;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

import seg.RelativeRho;
import doc.SampledPoint;
import doc.Stroke;

public class TrainData {

	public static class DataEntity {
		public double mean;
		public double var;

		public double min;
		public double max;

		public DataEntity(double m, double v, double i, double x) {
			mean = m;
			var = v;
			min = i;
			max = x;
		}

		public String toString() {
			StringBuffer buf = new StringBuffer();
			buf.append("data entity (\n");
			Field[] fs = DataEntity.class.getFields();
			for (Field f : fs) {
				try {
					buf.append("\t");
					buf.append(f.getName());
					buf.append("=");
					buf.append(f.getDouble(this));
					buf.append("\n");
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			buf.append("\t)");
			return buf.toString();
		}

		public String toWeka() {
//			System.out.println(toString());
			Field[] fs = DataEntity.class.getFields();
			StringBuffer buf = new StringBuffer();
			for (Field f : fs) {
				try {
					buf.append(f.getDouble(this) + ",");
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			return buf.toString();
		}

		public static String[] getWekaDeclarations() {
			Field[] fs = DataEntity.class.getFields();
			String[] ss = new String[fs.length];
			for (int i = 0; i < ss.length; i++) {
				ss[i] = "@attribute " + fs[i].getName() + " real";
				System.out.println(fs[i].getName());
			}
			return ss;
		}
	}

	private static int K = 3;

	public static final String TRAIN_SAMPLE_DIR = "C:\\Workspace\\Exp\\segmentation\\train\\";

	private static List<DataEntity> constData;

	private static List<DataEntity> varData;

	private static void initDataSet() {
		constData = new ArrayList<DataEntity>();
		varData = new ArrayList<DataEntity>();

		String pre = TRAIN_SAMPLE_DIR + "train.";

		String suf = "const.";
		for (int i = 1; i <= 30; i++) {
			String file = pre + suf + Integer.toString(i);
			Stroke s = parseStrokeFromFile(new File(file));
			constData.add(processStroke(s));
		}

		suf = "var.";
		for (int i = 1; i <= 20; i++) {
			String file = pre + suf + Integer.toString(i);
			Stroke s = parseStrokeFromFile(new File(file));
			varData.add(processStroke(s));
		}
	}

	public static DataEntity processStroke(Stroke s) {
		s.preprocess();

		SampledPoint ps[] = s.getPoints();
		double rhos[] = RelativeRho.calcRhos(ps, getK());

		DataEntity en = new DataEntity(GaussianModel.calcMean(rhos),
				GaussianModel.calcDev(rhos),
				DoubleStat.min(rhos),
				DoubleStat.max(rhos));
		return en;
	}

	public static Stroke parseStrokeFromFile(File file) {
		return Stroke.getFromFile(file);
	}

	public static int getK() {
		return K;
	}

	public static void setK(int k) {
		K = k;
	}

	public void outputWekaFile(File file) {
		initDataSet();

		try {
			BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file)));

			bw.write("@relation stroke\n\n");
			String ss[] = DataEntity.getWekaDeclarations();
			for (String s : ss) {
				bw.write(s + "\n");
			}
			bw.write("@attribute const {yes, no}\n\n");

			bw.write("@data\n");

			for (DataEntity en : constData) {
				bw.write(en.toWeka() + "yes" + "\n");
			}
			for (DataEntity en : varData) {
				bw.write(en.toWeka() + "no" + "\n");
			}

			bw.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		for (int i = 2; i < 10; i++) {
			int n = i;
			TrainData.setK(n);
			TrainData td = new TrainData();
			td.outputWekaFile(new File("train" + "." + Integer.toString(n) + ".arff"));
		}
	}
}
